home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / char / atari_serial.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  9.4 KB  |  325 lines

  1.  
  2. /*
  3.  * atari_serial.h: Common definitions for all Atari serial ports
  4.  *
  5.  * Copyright 1994 Roman Hodek
  6.  *   EMail: rnhodek@cip.informatik.uni-erlangen.de (Internet)
  7.  *      or: Roman_Hodek@n.maus.de (MausNet, NO mail > 16 KB!)
  8.  *
  9.  * This file is subject to the terms and conditions of the GNU General Public
  10.  * License.  See the file README.legal in the main directory of this archive
  11.  * for more details.
  12.  *
  13.  */
  14.  
  15.  
  16. #ifndef _ATARI_SERIAL_H
  17. #define _ATARI_SERIAL_H
  18.  
  19. #include <linux/tty.h>
  20.  
  21. /* 4 is sufficient for now... */
  22. #define    NR_PORTS 4
  23.  
  24.  
  25. /* Structure describing one bit in a register that may be high- or
  26.  * low-active. This is used for RI detection, because the location of
  27.  * this signal varies widely. The function TEST_BITPOS() is provided
  28.  * to return the status of such a bit.
  29.  */
  30.  
  31. typedef struct {
  32.     volatile unsigned char    *addr;            /* address of register */
  33.     unsigned char            bitno;            /* bit#, 0..7 */
  34.     unsigned char            active_state;    /* 1 for high-active,
  35.                                              * 0 for * low-active */
  36. } BITPOS;
  37.  
  38. static __inline__ int TEST_BITPOS( BITPOS bp )
  39.  
  40. {
  41.     return( !bp.addr ? 0 :
  42.             !!(*(bp.addr) & (1 << bp.bitno)) == bp.active_state );
  43. }
  44.     
  45.  
  46. /* Atari serial port types are numbered from 100 to avoid interference
  47.  * with the PC types (1..4)
  48.  */
  49. typedef enum {
  50.     SCC_NORM = 100,    /* standard SCC channel */
  51.     SCC_DMA,        /* SCC channel with DMA support */
  52.     MFP_CTRL,        /* standard MFP port with modem control signals */
  53.     MFP_BARE,        /* MFP port without modem controls */
  54. } SERTYPE;
  55.  
  56. /* This function tables does the abstraction from the underlying
  57.  * hardware:
  58.  *
  59.  *   init(): Initialize the port as necessary, set RTS and DTR and
  60.  *      enable interrupts. It does not need to set the speed and other
  61.  *      parameters, because change_speed() is called, too.
  62.  *   deinit(): Stop the port (wait for all characters to be sent,
  63.  *      disable interrupts)
  64.  *   enab_tx_int(): Enable or disable the Tx Buffer Empty interrupt
  65.  *      independantly from other interrupt sources. The pointer to
  66.  *      this function may be NULL, if there is no way to do this or it
  67.  *      is too complex. This Tx ints are just disabled to save some
  68.  *      interrupts if the transmitter is stopped anyway.
  69.  *   check_custom_divisor(): Check the given custom divisor for legality
  70.  *      and return 0 if OK, non-zero otherwise.
  71.  *   change_speed(): Set port speed, character size, number of stop
  72.  *      bits and parity from the termios structure. If the user wants
  73.  *      to set the speed with a custom divisor, he is required to
  74.  *      check the baud_base first!
  75.  *   restart(): Is called every time new data arrived in the Tx queue
  76.  *      and may be used to restart the transmitter if it ran empty.
  77.  *      'c' is the first character to be output or -1 if there is
  78.  *      none. If more than one character can be written (FIFOs!), you
  79.  *      have to take the remaining ones from the write queue directly.
  80.  *      This function is called with interrupts off.
  81.  *   throttle(): Set or clear the RTS line according to 'status'.
  82.  *   set_break(): Set or clear the 'Send a Break' flag.
  83.  *   get_serial_info(): Fill in the baud_base and custom_divisor
  84.  *      fields of a serial_struct. It may also modify other fields, if
  85.  *      needed.
  86.  *   get_modem_info(): Return the status of RTS, DTR, DCD, RI, DSR and CTS.
  87.  *   set_modem_info(): Set the status of RTS and DTR according to
  88.  *      'new_dtr' and 'new_rts', resp. 0 = clear, 1 = set, -1 = don't change
  89.  *   ioctl(): Process any port-specific ioctl's. This pointer may be
  90.  *      NULL, if the port has no own ioctl's.
  91.  *
  92.  */
  93.  
  94. struct async_struct;
  95.  
  96. typedef struct {
  97.     void (*init)( struct async_struct *info );
  98.     void (*deinit)( struct async_struct *info, int leave_dtr );
  99.     void (*enab_tx_int)( struct async_struct *info, int enab_flag );
  100.     int  (*check_custom_divisor)( struct async_struct *info, int divisor );
  101.     void (*change_speed)( struct async_struct *info );
  102.     void (*restart)( struct async_struct *info, int c );
  103.     void (*throttle)( struct async_struct *info, int status );
  104.     void (*set_break)( struct async_struct *info, int break_flag );
  105.     void (*get_serial_info)( struct async_struct *info,
  106.                              struct serial_struct *retinfo );
  107.     unsigned int (*get_modem_info)( struct async_struct *info );
  108.     int  (*set_modem_info)( struct async_struct *info, int new_dtr,
  109.                             int new_rts );
  110.     int  (*ioctl)( struct tty_struct *tty, struct file *file,
  111.                    struct async_struct *info, unsigned int cmd,
  112.                    unsigned long arg );
  113. } SERIALSWITCH;
  114.  
  115.  
  116. /* This is a modified version of the PC-Linux async_struct. Mainly,
  117.  * stuff like port address, xmit_fifo_size and the like are left out
  118.  * and other information fields were added.
  119.  */
  120.  
  121. struct async_struct {
  122.     /* Atari specific fields */
  123.     SERTYPE                type;         /* UART type */
  124.     volatile void        *base;        /* base address */
  125.     BITPOS                RI;            /* Where the Ring Indicator is signalled */
  126.     SERIALSWITCH        *sw;        /* functions to manage this port */
  127.     /* common fields */
  128.     int                    flags;
  129.     struct tty_struct     *tty;
  130.     int                    timeout;
  131.     int                    custom_divisor;
  132.     int                    x_char;        /* xon/xoff characater */
  133.     int                    close_delay;
  134.     int                    event;
  135.     int                    line;
  136.     int                    count;        /* # of fd on device */
  137.     int                    blocked_open; /* # of blocked opens */
  138.     long                session;    /* Session of opening process */
  139.     long                pgrp;        /* pgrp of opening process */
  140.     struct termios        normal_termios;
  141.     struct termios        callout_termios;
  142.     struct wait_queue    *open_wait;
  143.     struct wait_queue    *close_wait;
  144.     struct wait_queue    *xmit_wait;
  145. };
  146.  
  147. /*
  148.  * Events are used to schedule things to happen at timer-interrupt
  149.  * time, instead of at rs interrupt time.
  150.  */
  151. #define RS_EVENT_READ_PROCESS    0
  152. #define RS_EVENT_WRITE_WAKEUP    1
  153. #define RS_EVENT_HANGUP        2
  154. #define RS_EVENT_BREAK        3
  155. #define RS_EVENT_OPEN_WAKEUP    4
  156.  
  157.  
  158.  
  159. /***************************** Prototypes *****************************/
  160.  
  161. void rs_stop( struct tty_struct *tty );
  162. void rs_start( struct tty_struct *tty );
  163. void rs_write( struct tty_struct * tty );
  164. void rs_throttle( struct tty_struct * tty, int status );
  165. void rs_hangup( struct tty_struct *tty );
  166. int rs_open( struct tty_struct *tty, struct file * filp );
  167. long rs_init( long kmem_start );
  168.  
  169. /************************* End of Prototypes **************************/
  170.  
  171.  
  172.  
  173. /*************************** Inline Functions *************************/
  174.  
  175.  
  176. #include <linux/interrupt.h>
  177. #include <asm/bitops.h>
  178.  
  179. /*
  180.  * This routine is used by the interrupt handler to schedule
  181.  * processing in the software interrupt portion of the driver.
  182.  * It is needed in the port-specific interrupt handlers, so it is
  183.  * declared here in the common header.
  184.  */
  185.  
  186. extern char rs_event[];
  187.  
  188. static inline void rs_sched_event( struct async_struct *info, int event )
  189.  
  190. {
  191.     info->event |= 1 << event;
  192.     set_bit(info->line, rs_event);
  193.     mark_bh(SERIAL_BH);
  194. }
  195.  
  196.  
  197. /* The following functions do common tasks needed in the interrupt
  198.  * service routine(s):
  199.  * 
  200.  *  - Putting a character into the read_queue, either with or without
  201.  *    an error condition, and waking up processes waiting for
  202.  *    something to arrive
  203.  *  - Check if a throttle is needed due to the read queue getting full
  204.  *  - Removing a character from the write queue, obeying pending flow
  205.  *    control characters
  206.  *  - Checking for enough characters in the write queue to wake up
  207.  *    sleeping processes
  208.  *  - Doing required actions on wait queues if DCD has changed
  209.  *  - Doing required actions on wait queues if CTS has changed;
  210.  *    returns non-zero, if the transmitter should be restarted
  211.  */
  212.  
  213. static __inline__ void rs_put_char_to_queue( struct async_struct *info,
  214.                                              int c, int err )
  215.  
  216. {    struct tty_queue    *q = &info->tty->read_q;
  217.     
  218.     if (!FULL(q)) {
  219.  
  220.         if (err) {
  221.             if (err == TTY_BREAK)
  222.                 rs_sched_event( info, RS_EVENT_BREAK );
  223.  
  224.             /* ignore parity errors if parity checking isn't enabled. */
  225.             if (!(err == TTY_PARITY && !I_INPCK(info->tty))) {
  226.                 set_bit( q->head, &info->tty->readq_flags );
  227.                 c = err;
  228.             }
  229.         }
  230.  
  231.         q->buf[q->head] = c;
  232.         INC(q->head);
  233.  
  234.         rs_sched_event( info, RS_EVENT_READ_PROCESS );
  235.     }
  236. }
  237.  
  238.  
  239. static __inline__ void rs_rx_throttle_if_needed( struct async_struct *info )
  240.  
  241. {    struct tty_queue    *q = &info->tty->read_q;
  242.  
  243.     if (LEFT(q) < RQ_THRESHOLD_LW &&
  244.         !set_bit( TTY_RQ_THROTTLED, &info->tty->flags))
  245.  
  246.         rs_throttle( info->tty, TTY_THROTTLE_RQ_FULL );
  247. }
  248.  
  249.  
  250. static __inline__ int rs_get_char_from_queue( struct async_struct *info )
  251.  
  252. {    int                    ch;
  253.     struct tty_queue    *q = &info->tty->write_q;
  254.  
  255.     if (info->x_char) {
  256.         ch = info->x_char;
  257.         info->x_char = 0;
  258.     }
  259.     else if (!EMPTY(q)) {
  260.         ch = q->buf[q->tail];
  261.         INC(q->tail);
  262.     }
  263.     else {
  264.         rs_stop( info->tty );
  265.         ch = -1;
  266.     }
  267.  
  268.     return( ch );
  269. }
  270.  
  271.  
  272. static __inline__ void rs_tx_wakeup_if_needed( struct async_struct *info )
  273.  
  274. {    struct tty_queue    *q = &info->tty->write_q;
  275.  
  276.     if (LEFT(q) > WAKEUP_CHARS) {
  277.         rs_sched_event( info, RS_EVENT_WRITE_WAKEUP );
  278.         if (info->tty->write_data_cnt) {
  279.             set_bit( info->tty->line, &tty_check_write );
  280.             mark_bh( TTY_BH );
  281.         }
  282.     }
  283. }
  284.  
  285.  
  286. static __inline__ void rs_dcd_changed( struct async_struct *info, int dcd )
  287.  
  288. {
  289.     if (!C_CLOCAL(info->tty)) {
  290.  
  291.         if (dcd)
  292.             rs_sched_event( info, RS_EVENT_OPEN_WAKEUP );
  293.         else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
  294.                    (info->flags & ASYNC_CALLOUT_NOHUP)))
  295.             rs_sched_event( info, RS_EVENT_HANGUP );
  296.     }
  297. }
  298.  
  299.  
  300. static __inline__ int rs_cts_changed( struct async_struct *info, int cts )
  301.  
  302. {
  303.     if (!C_CRTSCTS(info->tty) || (info->flags & ASYNC_CLOSING))
  304.         return( 0 );
  305.  
  306.     if (info->tty->hw_stopped) {
  307.         if (cts) {
  308.             info->tty->hw_stopped = 0;
  309.             rs_start( info->tty );
  310.             return( 1 );
  311.         }
  312.     }
  313.     else {
  314.         if (!cts) {
  315.             info->tty->hw_stopped = 1;
  316.             rs_stop( info->tty );
  317.         }
  318.     }
  319.  
  320.     return( 0 );
  321. }
  322.  
  323.  
  324. #endif /* _ATARI_SERIAL_H */
  325.